package com.tierstall.server;

import com.google.gwt.user.server.rpc.RemoteServiceServlet;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import com.tierstall.client.service.UsersService;
import com.tierstall.server.model.User;
import com.tierstall.shared.Logger;
import com.tierstall.shared.SessionInvalidException;
import com.tierstall.shared.UserDTO;
import com.tierstall.util.HibernateUtil;

@SuppressWarnings("serial")
public class UsersServiceImpl extends RemoteServiceServlet implements
		UsersService {

	private final HashMap<String, UserDTO> userMap = new HashMap<String, UserDTO>();
	ServiceHelper helper;

	
	public UsersServiceImpl() {
		System.out.println("Service initialized");
		helper = ServiceHelper.getInstance();
		initUsers();
	}

	private void initUsers() {
		// TODO: Create a real UID for each User
		//
		initUserList();
	}

	private void initUserList() {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			List users = session.createQuery("from User").list();
			User current = null;
			for (Iterator iterator = users.iterator(); iterator.hasNext();) {
				current = (User) iterator.next();
				userMap.put(current.getId().toString(), createUserDTO(current));
			}
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
	}

	public UserDTO addUser(String sessionId, UserDTO user) {
		if (user.getId() != null && !user.getId().equals(""))
			return updateUser(sessionId, user);
		else {
			Session session = HibernateUtil.getSessionFactory().openSession();
			Transaction transaction = null;
			String usrID = "";
			try {
				transaction = session.beginTransaction();
				usrID = ((UUID) session.save(new User(user))).toString();
				transaction.commit();
			} catch (HibernateException e) {
				transaction.rollback();
				e.printStackTrace();
			} finally {
				session.close();
			}
			System.out.println("UserID: " + usrID.toString());
			return user;
		}
	}

	public UserDTO updateUser(String sessionId, UserDTO user) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			session.update(new User(user));
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return user;
	}

	public Boolean deleteUser(String sessionId, String id) {
		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		try {
			transaction = session.beginTransaction();
			User user = (User) session.load(User.class, UUID.fromString(id));
			session.delete(user);
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return true;
	}

	public ArrayList<UserDTO> deleteUsers(String sessionId,
			ArrayList<String> ids) throws SessionInvalidException {

		for (int i = 0; i < ids.size(); ++i) {
			deleteUser(sessionId, ids.get(i));
		}

		return getUserDetails(sessionId);
	}

	public ArrayList<UserDTO> getUserDetails(String sessionId)
			throws SessionInvalidException {
		if (helper.checkSession(getSession(), sessionId)) {
			initUsers();
			ArrayList<UserDTO> userList = new ArrayList<UserDTO>();

			Iterator<String> it = userMap.keySet().iterator();
			while (it.hasNext()) {
				userList.add(userMap.get(it.next()));
			}

			return userList;
		} else
			throw new SessionInvalidException();
	}

	public UserDTO getUser(String sessionId, String id) {

		Session session = HibernateUtil.getSessionFactory().openSession();
		Transaction transaction = null;
		UserDTO user = null;
		try {
			transaction = session.beginTransaction();
			user = createUserDTO((User) session.load(User.class,
					UUID.fromString(id)));
			transaction.commit();
		} catch (HibernateException e) {
			transaction.rollback();
			e.printStackTrace();
		} finally {
			session.close();
		}
		return user;

		// initUsers();
		// return userMap.get(id);
	}

	private UserDTO createUserDTO(User user) {
		return new UserDTO(user.getId().toString(), user.getUsername(),
				user.getPassword(), user.getPermission(), user.getFirstname(),
				user.getLastname(), user.getEmail(), user.getDepartment());
	}
	
	private HttpSession getSession() {
		HttpServletRequest request = this.getThreadLocalRequest();
		return request.getSession();
		
		

}
}
